/*
 * Copyright (C) 2010 Seapeak.Xu
 *
 * fostmq may be copied only under the terms of the GNU General
 * Public License V3, which may be found in the fostmq source kit.
 *
 * Created on: 2010-11-1
 * Author: Seapeak.Xu
 */

#include <stdio.h>
#include <stdlib.h>
#include <sys/poll.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/times.h>
#include <sys/select.h>
#include <string.h>

#include "fost_typedef.h"
#include "fost_netstream.h"
#include "fost_logger.h"

int send_by_select_nb(int sockfd,int timeout,const char *buff,const int len)
{
	int lbytes = 0,result = 0;

	fd_set fds;
	struct timeval timespan;
	while(true)
	{
		timespan.tv_sec = timeout;
		timespan.tv_usec = 0;
		FD_ZERO(&fds);
		FD_SET(sockfd,&fds);

		result = (select(sockfd + 1,NULL,&fds,NULL,&timespan));
		if(result > 0 && FD_ISSET(sockfd,&fds))
		{
			result = send(sockfd,buff + lbytes,len - lbytes,0);
			if(0 < result)
			{
				lbytes += result;
				if(len == lbytes)
				{
					return 0;
				}
				continue;
			}

		}
		else if(0 == result)
		{
			log_warn("File:%s,Line:%d,Function:%s.send is timeout.",
					__FILE__,__LINE__,__FUNCTION__);
		}
		else
		{
			if(!(EAGAIN == errno || EWOULDBLOCK == errno))
			{
				log_error("File:%s,Line:%d,Function:%s.send is fail.Errno:%d,Info:%s.",
						__FILE__,__LINE__,__FUNCTION__,errno,strerror(errno));
				return errno;
			}

		}
	}
	return 0;
}


int recv_by_select_nb(int sockfd,int timeout,char *buff,const int len)
{
	int lbytes = 0,result = 0;

	fd_set fds;
	struct timeval timespan;
	while(true)
	{
		timespan.tv_sec = timeout;
		timespan.tv_usec = 0;
		FD_ZERO(&fds);
		FD_SET(sockfd,&fds);

		result = (select(sockfd + 1,&fds,NULL,NULL,&timespan));
		if(result > 0 && FD_ISSET(sockfd,&fds))
		{
			result = recv(sockfd,buff + lbytes,len - lbytes,0);
			if(0 < result)
			{
				lbytes += result;
				if(len == lbytes)
				{
					return 0;
				}
				continue;
			}
		}
		else if(0 == result)
		{
			log_warn("File:%s,Line:%d,Function:%s.send is timeout.",
					__FILE__,__LINE__,__FUNCTION__);
		}
		else
		{
			if(!(EAGAIN == errno || EWOULDBLOCK == errno))
			{
				log_error("File:%s,Line:%d,Function:%s.send is fail.Errno:%d,Info:%s.",
						__FILE__,__LINE__,__FUNCTION__,errno,strerror(errno));
				return errno;
			}

		}
	}
	return 0;
}


